<?php

class          Common_DataTable_Model_Csv 
    extends    Common_DataTable_Model_Abstract 
    implements Common_DataTable_Model_SelfDefining,
               Common_DataTable_Model_Sortable,
               Common_DataTable_Model_Groupable
{

    private $arr_headers = null;
    private $obj_model = null;
    
    public function __construct($str_csv, $arr_options = array()) {
        
        parent::__construct();
        
        $this->__addMixin(new Common_DataTable_Model_Mixin_HeaderDetector(), 'detector');
        
        $this->parse($str_csv, $arr_options);
        
        
    }
    
    protected function getModel() {
        return $this->obj_model;
    }
    
    protected function parse($str_csv, $arr_options = array()) {
        
        if (is_file($str_csv)) {
            $str_csv = file_get_contents($str_csv);
        }
        
        $str_delimiter = isset($arr_options['delimiter']) ? $arr_options['delimiter'] : null;
        $str_oel = isset($arr_options['eol']) ? $arr_options['eol'] : null;

        $arr_data = Utility_CsvFunctions::parseIntoArray($str_csv, $str_delimiter, $str_oel, $arr_options);
        
        if(isset($arr_options['number_of_headers'])) {
            $int_headers = (int) $arr_options['number_of_headers'];
            
            if($int_headers > 0) {
                
                $arr_temp = array_slice($arr_data, 0, $int_headers);
                $arr_data = array_slice($arr_data, $int_headers);
                
                $arr_last_headers = end($arr_temp);
                $arr_first_row = reset($arr_data);
                
                $arr_columns = array();
                foreach($arr_last_headers as $str_key => $mix_value) {
                    $mix_value = isset($arr_first_row[$str_key]) ? $arr_first_row[$str_key] : null;
                    $arr_columns[$str_key] = $this->detectHeaderDefinition($str_key, $mix_value);
                }
                
                $arr_temp_headers = array_slice($arr_temp, 0, -1);
                
                $arr_header_definition = null;
                
                $arr_headers = array();
                foreach($arr_temp_headers as $i => $arr_row) {
                    
                    $arr_headers[$i] = array();
                    foreach($arr_row as $str_key => $mix) {
                        
                        if(strlen($mix) > 0) {
                            
                            if(!is_null($arr_header_definition)) {
                                $arr_header_definition['children'] = $int_children;
                                $arr_headers[$i][] = $arr_header_definition;
                            }
                                
                            $int_children = 1;
                            
                            $arr_header_definition = $this->detectHeaderDefinition($mix);
                            $arr_header_definition['children'] = $int_children;
                            
                        } else {
                            
                            $int_children++;
                            
                        }
                        
                        
                    }
                    
                    if(!is_null($arr_header_definition)) {
                        $arr_header_definition['children'] = $int_children;
                        $arr_headers[$i][] = $arr_header_definition;
                    }
                }
                
                $arr_headers[] = $arr_columns;
                
                $this->arr_headers = $arr_headers;
            }
            
        } else if(isset($arr_options['data_keys']) && is_array($arr_options['data_keys'])) {
            
            $arr_data_keys = $arr_options['data_keys'];
            
            $arr_first_row = reset($arr_data);
            
            $arr_columns = array();
            foreach($arr_data_keys as $str_key) {
                
                $mix_value = isset($arr_first_row[$str_key]) ? $arr_first_row[$str_key] : null;
                
                $arr_header_definition = detectHeaderDefinition($str_key, $mix_value);
                
                $arr_columns[$str_key] = $arr_header_definition;
                
            }
            
            $this->arr_headers = array($arr_columns);
            
        }
        
        $this->obj_model = new Common_DataTable_Model_Array($arr_data);

    }
    
    public function getData($int_offset = null, $int_size = null) {
        return $this->getModel()->getData($int_offset, $int_size);
    }

    public function hasData() {
        return $this->getModel()->hasData();
    }
    
    public function sortDataBy($arr_sort_meta) {
        $this->getModel()->sortDataBy($arr_sort_meta);
    }
    
    public function groupDataBy($arr_group_meta) {
        $this->getModel()->groupDataBy($arr_group_meta);
    }
    
    public function getGroupDefinition() {
        return $this->getModel()->getGroupDefinition();
    }
    
    protected function hasHeaders() {
        return !is_null($this->arr_headers);
    }
    
    protected function getHeaders() {
        return $this->arr_headers;
    }
    
    public function defineHeaders() {
        
        $arr_headers = null;
        
        if($this->hasHeaders()) {
            $arr_headers = $this->getHeaders();
        } else {
            $this->getModel()->defineHeaders();
        }
        
        return $arr_headers;
    }
    
}
